Dynomotion

Group: DynoMotion Message: 11249 From: Hardy Family Date: 3/20/2015
Subject: Direct FPGA set/clear bit
Hi Tom,

I implemented I2C via bit-bang on my new breakout board, and am trying to optimize its speed.

Using the code that you provided on a previous thread (related to SPI, but should apply to I2C) I could not get the direct FPGA writes working.  The commented-out code does not work, but the normal function calls do work.  scl_bit is 30.

    for (;;) {
        //FPGA(BIT_SET+(scl_bit>>3)) = 1<<(scl_bit&7);
        //FPGA(BIT_CLR+(scl_bit>>3)) = 1<<(scl_bit&7);
        SetBit(scl_bit);
        ClearBit(scl_bit);
    }

Running this gives about 750ns between edges (1.5us period).  With the FPGA direct writes, the output stays high.

The reason I would like to use direct writes is that I have multiple bits to manipulate since I have 4 I2C buses (and the bit numbers are contiguous).  Since I/O is so slow, it is important to get the most possible work done with each I/O, so setting multiple bits at once is useful.

Using a Kflop with Kmotion version 432.

Regards,
SJH

Group: DynoMotion Message: 11250 From: TK Date: 3/20/2015
Subject: Re: Direct FPGA set/clear bit
Hi SJH,

BIT_CLR performs an "and" operation. Try adding a "not":
FPGA(BIT_CLR+(scl_bit>>3)) = ~(1<<(scl_bit&7));

Regards
TK

On Mar 20, 2015, at 12:27 PM, Hardy Family hardy.woodland.cypress@... [DynoMotion] <DynoMotion@yahoogroups.com> wrote:

 

Hi Tom,

I implemented I2C via bit-bang on my new breakout board, and am trying to optimize its speed.

Using the code that you provided on a previous thread (related to SPI, but should apply to I2C) I could not get the direct FPGA writes working.  The commented-out code does not work, but the normal function calls do work.  scl_bit is 30.

    for (;;) {
        //FPGA(BIT_SET+(scl_bit>>3)) = 1<<(scl_bit&7);
        //FPGA(BIT_CLR+(scl_bit>>3)) = 1<<(scl_bit&7);
        SetBit(scl_bit);
        ClearBit(scl_bit);
    }

Running this gives about 750ns between edges (1.5us period).  With the FPGA direct writes, the output stays high.

The reason I would like to use direct writes is that I have multiple bits to manipulate since I have 4 I2C buses (and the bit numbers are contiguous).  Since I/O is so slow, it is important to get the most possible work done with each I/O, so setting multiple bits at once is useful.

Using a Kflop with Kmotion version 432.

Regards,
SJH

Group: DynoMotion Message: 11251 From: Hardy Family Date: 3/21/2015
Subject: Re: Direct FPGA set/clear bit
Hi Tom,

That bitwise inversion was not in the SPI code you posted in the thread about getting SPI working.  Is this a difference in the FPGA since that time?

So tell me if I've got this right: writing to the BIT_CLR location turns off just those bits which have a zero in the written value?  And BIT_SET turns on only those with a '1'?

Also, since I am doing I2C which requires open collector drive, for the SDA lines I need to manipulate the I/O direction.  There is a BIT_DIR location for that, but I presume that I need to keep a shadow register for that to avoid affecting unrelated I/Os.

Is there an existing I/O direction shadow that I can use?

And one last question: is there a 16-bit version of those BIT_DIR locations?  The reason I ask is that I have had to use I/Os 34,35,44,45 for the 4 SDAs, so if there was a 16-bit write then I could hit all of those bits (selected from 32..47) in one fell swoop.  That would be awesome.  I see there's a #define FPGAW(X) macro in KMotionDef.h which looks like it would do the job, but I just want to make sure.

Regards,
SJH


On Fri, Mar 20, 2015 at 6:36 PM, TK tk@... [DynoMotion] <DynoMotion@yahoogroups.com> wrote:
 

Hi SJH,

BIT_CLR performs an "and" operation. Try adding a "not":
FPGA(BIT_CLR+(scl_bit>>3)) = ~(1<<(scl_bit&7));

Regards
TK

On Mar 20, 2015, at 12:27 PM, Hardy Family hardy.woodland.cypress@... [DynoMotion] <DynoMotion@yahoogroups.com> wrote:

 

Hi Tom,

I implemented I2C via bit-bang on my new breakout board, and am trying to optimize its speed.

Using the code that you provided on a previous thread (related to SPI, but should apply to I2C) I could not get the direct FPGA writes working.  The commented-out code does not work, but the normal function calls do work.  scl_bit is 30.

    for (;;) {
        //FPGA(BIT_SET+(scl_bit>>3)) = 1<<(scl_bit&7);
        //FPGA(BIT_CLR+(scl_bit>>3)) = 1<<(scl_bit&7);
        SetBit(scl_bit);
        ClearBit(scl_bit);
    }

Running this gives about 750ns between edges (1.5us period).  With the FPGA direct writes, the output stays high.

The reason I would like to use direct writes is that I have multiple bits to manipulate since I have 4 I2C buses (and the bit numbers are contiguous).  Since I/O is so slow, it is important to get the most possible work done with each I/O, so setting multiple bits at once is useful.

Using a Kflop with Kmotion version 432.

Regards,
SJH


Group: DynoMotion Message: 11252 From: Tom Kerekes Date: 3/21/2015
Subject: Re: Direct FPGA set/clear bit
Attachments :
Hi SJH,

>>>>That bitwise inversion was not in the SPI code you posted in the thread about getting SPI working.  Is this a difference in the FPGA since that time?
No sorry that was a bug in the code example.  Attached is a corrected version (untested)


>>>>So tell me if I've got this right: writing to the BIT_CLR location turns off just those bits which have a zero in the written value?  And BIT_SET turns on only those with a '1'?
Correct


>>>>Is there an existing I/O direction shadow that I can use?
Yes.  See code example we use below.   If you know there will be no Thread safe issues you can skip the atomic stuff

void SetBitDirection(int bit, int dir)
{                 
    if (bit < N_BITS)
    {
        unsigned int word = bit>>5;
        unsigned int port = bit>>3;
        unsigned int rbit = bit&31;
   
        if (dir)
            AtomicSet(&BitDirShadow[word], 1<<rbit);
        else
            AtomicClear(&BitDirShadow[word], ~(1<<rbit));
          
        FPGA(BIT_DIR+port) = (unsigned char)(BitDirShadow[word]>>(8*(port&3)));
    }
}


>>>>> is there a 16-bit version of those BIT_DIR locations
No sorry there isn't


Regards
TK